#region Using

using System;
using System.Text;
using System.Web;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Collections.Generic;
using BlogEngine.Core;

#endregion

namespace BlogEngine.Core.Web.HttpModules
{
	/// <summary>
	/// Handles pretty URL's and redirects them to the permalinks.
	/// </summary>
	public class PhotoUrlRewrite : IHttpModule
	{
		#region IHttpModule Members

		/// <summary>
		/// 
		/// </summary>
		public void Dispose()
		{
			// Nothing to dispose
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		public void Init(HttpApplication context)
		{
			context.BeginRequest += new EventHandler(context_BeginRequest);
		}

		#endregion

		/// <summary>
		/// Handles the BeginRequest event of the context control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void context_BeginRequest(object sender, EventArgs e)
		{
			HttpContext context = ((HttpApplication)sender).Context;
			string path = context.Request.Path.ToUpperInvariant();
			string url = context.Request.RawUrl.ToUpperInvariant();

			if (url.Contains(BlogSettings.Instance.FileExtension.ToUpperInvariant()) && !url.Contains("ERROR404.ASPX"))
			{
				if (url.Contains("/PHOTO/"))
				{
					RewritePhoto(context);
				}
				else if (url.Contains("/ALBUM/"))
				{
					RewriteAlbum(context);
				}
				else if (url.Contains("/GALLERY/"))
				{
					RewriteGallery(context);
				}

			}
		}

		/// <summary>
		/// Extracts the title from the requested URL.
		/// </summary>
		private static string ExtractTitle(HttpContext context, string url)
		{
			url = url.ToLowerInvariant();
			if (url.Contains(BlogSettings.Instance.FileExtension) && url.EndsWith("/"))
			{
				url = url.Substring(0, url.Length - 1);
				context.Response.AppendHeader("location", url);
				context.Response.StatusCode = 301;
			}

			url = url.Substring(0, url.IndexOf(BlogSettings.Instance.FileExtension));
			int index = url.LastIndexOf("/") + 1;
			string title = url.Substring(index);
			return context.Server.UrlEncode(title);
		}

		/// <summary>
		/// Gets the query string from the requested URL.
		/// </summary>
		/// <param name="context">The context.</param>
		/// <returns></returns>
		private static string GetQueryString(HttpContext context)
		{
			string query = context.Request.QueryString.ToString();
			if (!string.IsNullOrEmpty(query))
				return "&" + query;

			return string.Empty;
		}

		private static Regex _GuidRegex = new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$", RegexOptions.Compiled);
		/// <summary>
		/// Determines if the express is a valid guid
		/// </summary>
		public static bool IsGUID(string expression)
		{
			if (expression != null)
				return _GuidRegex.IsMatch(expression);

			return false;
		}

		/// <summary>
		/// Extracts the title from the requested URL.
		/// </summary>
		private static string ExtractGuid(HttpContext context)
		{
			int index = context.Request.RawUrl.ToLowerInvariant().LastIndexOf("/") + 1;
			int stop = context.Request.RawUrl.ToLowerInvariant().LastIndexOf(BlogSettings.Instance.FileExtension);
			string title = context.Request.RawUrl.Substring(index, stop - index).Replace(BlogSettings.Instance.FileExtension, string.Empty);
			return context.Server.UrlEncode(title);
		}

		/// <summary>
		/// Extracts the title from the requested URL.
		/// </summary>
		private static int ExtractPageBeforeGuid(HttpContext context)
		{
			string query = context.Request.RawUrl.ToLowerInvariant();
			int index = query.LastIndexOf("/") + 1;

			if (index < 0)
				return 0;

			string query2 = query.Substring(0, index - 1);
			int index2 = query2.LastIndexOf("/");

			if (index2 < 0)
				return 0;

			string pagenbr = query2.Substring(index2 + 1, query2.Length - index2 - 1);

			int page = 0;

			if (!Int32.TryParse(pagenbr, out page))
				return 0;

			return page;
		}


		private static void RewritePhoto(HttpContext context)
		{
			string id = ExtractGuid(context);

			Photo photo = null;

			if (IsGUID(id))
				photo = Photo.GetById(new Guid(id));
			else
				photo = Photo.GetBySlug(id);

			if (photo != null)
				context.RewritePath("~/photo.aspx?id=" + photo.Id.ToString() + GetQueryString(context), false);
		}

		private static void RewriteGallery(HttpContext context)
		{
			int page = ExtractPageBeforeGuid(context);

			context.RewritePath("~/gallery.aspx?page=" + page.ToString() + GetQueryString(context), false);
		}

		private static void RewriteAlbum(HttpContext context)
		{
			string id = ExtractGuid(context);
			int page = ExtractPageBeforeGuid(context);

			Album album = null;

			if (IsGUID(id))
				album = Album.GetById(new Guid(id));
			else
				album = Album.GetBySlug(id);

			if (album != null)
				context.RewritePath("~/album.aspx?id=" + album.Id.ToString() + "&page=" + page.ToString() + GetQueryString(context), false);
		}
	}
}